#include "Common/Common.h"
#include "PropertyMapper.h"

using namespace cmn;

editor_core::PropertyValueType StringToValueType( const std::string& valueType );
std::string ValueTypeToString( editor_core::PropertyValueType valueType );

wxPGProperty* PropertyMapper::ToWxProperty( const editor_core::Property& property ) {
	wxString key;
	key.Printf( "%d_%s", property.GetKey(), ValueTypeToString( property.GetValue().GetType() ) );

	wxString name( property.GetName() );

	Vector<editor_core::Property> children;
	property.GetChildren( children );

	if( children.GetLength() > 0 ) {
		wxPGProperty* composedProp = new wxStringProperty( name, key, "<composed>" );
		composedProp->Enable( false );
		return composedProp;
	}

	editor_core::PropertyValue value = property.GetValue();
	switch( value.GetType() ) {
		case editor_core::PropertyValueType::Bool:
			return new wxBoolProperty( name, key, value.GetBool() );
		case editor_core::PropertyValueType::Int:
			return new wxIntProperty( name, key, value.GetInt() );
		case editor_core::PropertyValueType::Float:
			return new wxFloatProperty( name, key, value.GetFloat() );
		case editor_core::PropertyValueType::String:
			return new wxStringProperty( name, key, value.GetString() );
		case editor_core::PropertyValueType::File:
			return new wxFileProperty( name, key, value.GetFile() );
		default:
			throw ProductException( "Unknown property type" );
	}
}

editor_core::Property PropertyMapper::ToEditorProperty( const wxPGProperty* property ) {
	std::string propertyPath = property->GetName().ToStdString();

	size_t lastDotIndex = propertyPath.find_last_of( '.' );
	std::string keyAndTypeStr =
		lastDotIndex == std::string::npos
		? propertyPath
		: propertyPath.substr( lastDotIndex + 1, propertyPath.length() - lastDotIndex - 1 );

	size_t underlineIndex = keyAndTypeStr.find( '_' );
	std::string keyStr = keyAndTypeStr.substr( 0, underlineIndex );
	std::string typeStr = keyAndTypeStr.substr( underlineIndex + 1, keyAndTypeStr.length() - underlineIndex - 1 );
	std::string name = property->GetLabel().ToStdString();

	wxVariant value = property->GetValue();
	int key = atoi( keyStr.c_str() );

	int childrenCount = property->GetChildCount();
	if( childrenCount > 0 )
		return editor_core::Property( key, name, editor_core::PropertyValue::CreateIntValue( 0 ) );

	editor_core::PropertyValueType propValueType = StringToValueType( typeStr );
	switch( propValueType ) {
		case editor_core::PropertyValueType::Bool:
			return editor_core::Property( key, name, editor_core::PropertyValue::CreateBoolValue( value.GetBool() ) );
		case editor_core::PropertyValueType::Int:
			return editor_core::Property( key, name, editor_core::PropertyValue::CreateIntValue( value.GetInteger() ) );
		case editor_core::PropertyValueType::Float:
			return editor_core::Property( key, name, editor_core::PropertyValue::CreateFloatValue( float( value.GetDouble() ) ) );
		case editor_core::PropertyValueType::File:
			return editor_core::Property( key, name, editor_core::PropertyValue::CreateFileValue( value.GetString().ToStdString() ) );
		case editor_core::PropertyValueType::String:
			return editor_core::Property( key, name, editor_core::PropertyValue::CreateStringValue( value.GetString().ToStdString() ) );
		default:
			throw ProductException( "Unknown property type" );
	}
}

editor_core::PropertyValueType StringToValueType( const std::string& valueType ) {
	if( valueType == "BOOL" ) return editor_core::PropertyValueType::Bool;
	if( valueType == "INT" ) return editor_core::PropertyValueType::Int;
	if( valueType == "FLOAT" ) return editor_core::PropertyValueType::Float;
	if( valueType == "STRING" ) return editor_core::PropertyValueType::String;
	if( valueType == "FILE" ) return editor_core::PropertyValueType::File;
	throw ProductException( "Unknown property type" );
}

std::string ValueTypeToString( editor_core::PropertyValueType valueType ) {
	switch( valueType ) {
		case editor_core::PropertyValueType::Bool:
			return "BOOL";
		case editor_core::PropertyValueType::Int:
			return "INT";
		case editor_core::PropertyValueType::Float:
			return "FLOAT";
		case editor_core::PropertyValueType::String:
			return "STRING";
		case editor_core::PropertyValueType::File:
			return "FILE";
		default:
			throw ProductException( "Unknown property type" );
	}
}
